/*
 * main.c
 *
 *  Created on: June 23, 2023
 *      Author: mcealt_DS
 */


#include "bsp_init.h"
#include "em_emu.h"
#include "DS_test.h"
#include "app_log.h"
#include "softwareMultiTimer.h"
#include "mac_transmitter.h"
#include "mac_receiver.h"
#include "mac_timeSync.h"
#include "mac_fhss.h"
#include "mac_packethandle.h"
#include "net_rolling_code.h"
#include "util.h"
#include "net_packet.h"
#include "net_protocol.h"
#define PRINTF_TEST APP_PRINTF_HEX
#include "app_api.h"
#include "app_cli_cmd.h"
#include "app_key_value.h"
#include "device_type.h"
#include "net_file.h"
#include "app_filetransport_api.h"
#include "net_logout.h"
#include "bsp_rmu.h"
#include "net_register.h"

#ifdef HUB_DEVICE
#include "app_hub_api.h"
#else
#if(FILE_FLASH_ENABLE)
#include "app_multislot.h"
#endif
#endif

static STATEM_TYPE_ST    s_stMacTxStateMEvent ;
static STATEM_TYPE_ST    s_stMacRxStateMEvent ;

static MultiTimer powerOnTimer;
#ifdef RFM_DEVICE

#if defined(SM_SMART_PLUG) || defined(SM_WS)
#define HEAT_BEAT_DELAY (39321) //1200ms
#else
#define HEAT_BEAT_DELAY (8192)  //250ms
#endif

static void powerOnCimmissionHeartBeatTimerCallback(MultiTimer* timer, void *userData)
{
  (void)timer;
  (void)userData;

  if(DS_RSTCAUSE_POR == getRestReason() && isBattVoltageHigh() && device_test_sleep_state_get()) //Todo 且isBattVoltageHigh(), 返回true表示电压大于50%能支撑注册包发送，或为常供电设备
  {
      startCommissiongJoin(startUpTrigger, other_device);//未注册状态 上电立即注册，不判断电压
  }

  if(isregeist() == true)//已注册状态开启心跳
  {
#ifndef SPVN_DISABLE
      startSpvnTimer(1);    //开启心跳，默认5min
      setMacTransEvent(EN_TRANS_REQ_SPVN, 0x00, ADHOC_RETRY_COUNT_MAX ,LBT_REDO_COUNT_MAX);
#endif
  }
}
#endif

void gotoSleep(void)
{
//  bool sleepAllowed = false;
  staticPowerGpioInit();
  if(isTxStateRfIdle() && isRxStateRfIdle()){ //Info 0513 针对系统最长报文、超时时间增加到255字节+255字节+20字节？
//    if(RAIL_Sleep(0, &sleepAllowed) == RAIL_STATUS_NO_ERROR){//Info 0510 若rail非idle状态 此处会失败
//       if(sleepAllowed){
//        EMU_EnterEM3(false); //若TxState处于Idle，且 RxState处于Idle且无常收事件，进入最低功耗模式
////        RAIL_Wake(0); //sleep与wake必须配对产生
//       }
//        else{
//            s_RailSleepFailCnt[0] ++;
//        }
//
//       RAIL_Wake(0); //sleep与wake必须配对产生 ;; 仅测试，故意制造非配对场景
//    }
//    else{
//        s_RailSleepFailCnt[1] ++;
//    }

      EMU_EnterEM3(false); //若TxState处于Idle，且 RxState处于Idle且无常收事件，进入最低功耗模式
  }
  else{
    EMU_EnterEM1(); //ToDo，或许可不进入该模式
  }

}



int main(void)
{
  PFUNC_TX_CALLBACK pTxCallbackArray[EN_TRANS_REQ_MAX];

  bsp_init();                         /* bsp init         */

#ifdef HUB_DEVICE
  DS_hub_api_init();
  reg_getInvalid_init();
#else
#if(FILE_FLASH_ENABLE)
  app_bootloader_init();
#endif
#endif
  DS_file_api_init();
#ifdef CLI_CMD
  cli_cmd_init();
#endif
  net_init();

  test_gpio_level_get();
  SM_main();


  pTxCallbackArray[EN_TRANS_REQ_SYNC_BCAST]=mac_txStatecallbackBcast;
  pTxCallbackArray[EN_TRANS_REQ_ADHOC_SPVN_ACK]=txStatecallbackAck;
  pTxCallbackArray[EN_TRANS_REQ_FILE_DATA_TX]=mac_txStatecallbackFileDataTx;
  pTxCallbackArray[EN_TRANS_REQ_REALTIME_BCAST]=mac_txStatecallbackRealTimeBcast;
  pTxCallbackArray[EN_TRANS_REQ_REGISTER] = txStatecallbackCommissiong;
  pTxCallbackArray[EN_TRANS_REQ_ADHOC_UPLINK]=mac_txStatecallbackAdhocUp;
  pTxCallbackArray[EN_TRANS_REQ_ADHOC_DOWNLINK_START]=txStatecallbackAdhocDown0;
  pTxCallbackArray[EN_TRANS_REQ_ADHOC_DOWNLINK_START+1]=mac_txStatecallbackAdhocDown1;
  pTxCallbackArray[EN_TRANS_REQ_ADHOC_DOWNLINK_START+2]=mac_txStatecallbackAdhocDown2;
  pTxCallbackArray[EN_TRANS_REQ_ADHOC_DOWNLINK_START+3]=mac_txStatecallbackAdhocDown3;
  pTxCallbackArray[EN_TRANS_REQ_ADHOC_DOWNLINK_START+4]=mac_txStatecallbackAdhocDown4;
  pTxCallbackArray[EN_TRANS_REQ_SPVN]=mac_txStatecallbackAdhocSpvn;
  macTxStateMachineInit(pTxCallbackArray);
  macRxStateMachineInit(RxCallback);

  initFhssSequence(0x112233,0);
#ifdef RFM_DEVICE
    if(isregeist() == false)
    {
        if(DS_RSTCAUSE_POR == getRestReason())
        {
            //延时250ms发注册包
            softwareMultiTimerStart(EN_LP_HARD_TIMER_EM3_SYS_RTC_1, &powerOnTimer, 8192, powerOnCimmissionHeartBeatTimerCallback,NULL,0);
        }
    }
    else
    {
      //延时250ms发注册包和心跳
      softwareMultiTimerStart(EN_LP_HARD_TIMER_EM3_SYS_RTC_1, &powerOnTimer, HEAT_BEAT_DELAY, powerOnCimmissionHeartBeatTimerCallback,NULL,0);
    }
#ifdef SLEEP_DEVICE
  #ifndef SPVN_DISABLE //无心跳则无RxWake
    startRxWakeTimer(1); //开启RxWake
  #endif
#else
    setMacRecvEvent(EN_RECV_REQ_ALWAYS_ON_CHAN,RF_CHAN_RESYNC_DEFAULT_NUMBER);
    startAlwaysRxMainChanUpdateTimer(1);
#endif
    
#else
  setMacRecvEvent(EN_RECV_REQ_ALWAYS_ON_CHAN,RF_CHAN_RESYNC_DEFAULT_NUMBER);
  startAlwaysRxMainChanUpdateTimer(1);
  startSyncBcastTimer(1); //开启同步广播通道
#endif

  DS_app_log_error("Sysclk=%ldhz \n ",CMU_ClockFreqGet(cmuClock_SYSCLK));

  while(1)
  {
      SM_process();
      net_while();
      timeSyncEventCheck();
#ifdef CLI_CMD
      DS_cli_cmd_process();
#endif
#ifdef SLEEP_DEVICE //休眠设备
      //休眠判断 check 先全局保护之
      CORE_DECLARE_IRQ_STATE;
      CORE_ENTER_CRITICAL();
      //bug0823 该判断存在就近效应，导致非第1判断语句永远无法跑到，使用& 代替 && 避免短路现象
      if((false == macTxStateMachineEventCheck(&s_stMacTxStateMEvent)
         & false == macRxStateMachineEventCheck(&s_stMacRxStateMEvent))
         /*& 其他条件*/
          && (true == is_buff_key_value_down_empty())
          && (true == device_sleep_state_get())
          && (true == device_test_sleep_state_get())

        ){ //允许休眠
          timeSyncEventCheck();//休眠前处理所有事件标志位
          gotoSleep();
          CORE_EXIT_CRITICAL();

          //检查产生的事件类型，先Rx事件后Tx
          macRxStateMachineEventCheck(&s_stMacRxStateMEvent);
      }
      else{
          CORE_EXIT_CRITICAL();
      }
      macRxStateMachineRun(&s_stMacRxStateMEvent);
      macTxStateMachineEventCheck(&s_stMacTxStateMEvent);//处理上次Rx后可能产生的Tx事件，以快速响应之
      macTxStateMachineRun(&s_stMacTxStateMEvent);

#else //不休眠设备
      macRxStateMachineEventCheck(&s_stMacRxStateMEvent);
      macRxStateMachineRun(&s_stMacRxStateMEvent);
#ifdef RFM_DEVICE
      SM_process();//接收无线报文后，子设备先处理之后，再发送无线报文
#endif
      macTxStateMachineEventCheck(&s_stMacTxStateMEvent);//处理上次Rx后可能产生的Tx事件，以快速响应之
      macTxStateMachineRun(&s_stMacTxStateMEvent);
#endif


#ifdef HUB_DEVICE
      DS_hub_api_task();
      reg_delInvalidRFMId_task();
#endif
      DS_file_api_task();
  }
}
